/**
 @author 迷途小羔羊
 2015.3.5
 */
module GYLite
{
										
		
	export class GYGridV extends GYGridBase
	{
				
		protected _vScroller:GYScrollBarV;
		/**垂直滚动Grid组件
		@inheritDoc*/
		public constructor(sizeW:number,sizeH:number,getGridFunc:Function=null, getThisObject:any=null, setGridFunc:Function=null, setThisObject:any=null)
		{
			super(sizeW,sizeH,getGridFunc,getThisObject,setGridFunc,setThisObject);			
		}
		protected initComponent():void
		{var s = this;
			super.initComponent();
			s._vScroller=new GYScrollBarV;
			s._vScroller.maximum = 0;
			s._vScroller.value = 0;
			s._vScroller.right = 0;
			s._vScroller.addEventListener(GYScrollerEvent.SCROLL_CHANGE, s.scrollChange,s);
			s._vScroller.addEventListener(GYScrollerEvent.SCROLL_TWEEN_END,s.scrollEnd,s);
			if(s._rows != 0 && s._cols != 0)
			{
				var grid:IItemRender;
				grid=s.getGrid();				
				s._boxH = grid.height;
				s._boxW = grid.width;
				grid.dispose();
				if(s._rows > 0)
				{
					s.height = s._rows;
					s.width = s._cols;
				}
				else
				{
					s.rows = -s._rows;
					s.cols = -s._cols;
				}
			}
		}
		/**inheritDoc*/
		public scrollToIndex(val:number):void
		{var s = this;
			s._vScroller.position = ((val / s._cols) >> 0) * s._boxH;
		}
		/**inheritDoc*/
		public scrollToEndIndex(val:number):void
		{var s = this;
			s._vScroller.position = ((val / s._cols) >> 0) * s._boxH - s._innerHeight + s._boxH;
		}
		protected selectLine(data:any,selectedData:any,ctrlKey:boolean,checkNext:boolean=false):void
		{var s = this;
			var ind:number=0,stInd:number=0,endInd:number=0;
			var tempData:any;
			var i:number=0,len:number=0;
			var tempVec:any[];
			var tempItem:IItemRender;
			var end:number=0,tempInd:number=0;
			var flag:number=0,mY:number = s.mouseY,mX:number = s.mouseX;
			var leftInd:number=0,rightInd:number=0;
			var selectCol:number=0,selectMax:number=0;
			if(checkNext)
			{
				if(mY > s.height)
					flag = 1;
				else if(mY < 0)
					flag = -1;
				selectCol = mX / s._boxW;
				if(flag == 0)
					return;
			}
			stInd = s._dataProvider.indexOf(selectedData);
			endInd = s._dataProvider.indexOf(data);
			if(flag != 0)
			{
				if(flag == 1)
				{
					endInd += s._cols;
					endInd = endInd - endInd % s._cols + selectCol;
					selectMax = s._dataProvider.length - s._dataProvider.length % s._cols + selectCol;
					if(selectMax >= s._dataProvider.length)
						selectMax = s._dataProvider.length - 1;
					endInd = endInd < selectMax? endInd: selectMax;
					data = s._dataProvider[endInd];
				}
				else if(flag == -1)
				{
					endInd -= s._cols;
					endInd = endInd - endInd % s._cols + selectCol;
					endInd = endInd > 0? endInd:0;
					data =  s._dataProvider[endInd];
				}
				s.scrollToEndIndex(endInd);
			}
			s._nextData = data;
			if(endInd < stInd)
			{
				ind = endInd;
				endInd = stInd;
				stInd = ind;
			}
			len = endInd + 1;
			end = s._selectList.length-1;
			if(s._selectMode == 0)
			{
				leftInd = stInd % s._cols;
				rightInd = endInd % s._cols;
				if(rightInd < leftInd)
				{
					ind = rightInd;
					rightInd = leftInd;
					leftInd = ind;
				}
				for(i=stInd;i<len;++i)
				{
					if(s._selectList.length >= s._canSelectNum)
						break;
					tempInd = i % s._cols;
					if(tempInd < leftInd || tempInd > rightInd)
						continue;
					tempData = s._dataProvider[i];
					ind = end > -1? s._selectList.lastIndexOf(tempData,end) : -1;
					if(ind == -1)
					{
						if(tempData)
						{
							tempItem = s._dataToItemDict.getValue(tempData);
							s._selectList.push(tempData);
							if(tempItem)
								tempItem.selected = true;
						}
					}
					else if(!ctrlKey)
					{
						tempData = s._selectList[end];
						s._selectList[end] = s._selectList[ind];
						s._selectList[ind]= tempData;
						--end;
					}
				}
			}
			else
			{
				for(i=stInd;i<len;++i)
				{
					tempData = s._dataProvider[i];
					ind = end > -1? s._selectList.lastIndexOf(tempData,end) : -1;
					if(ind == -1)
					{
						if(s._selectList.length >= s._canSelectNum)
							continue;
						if(tempData)
						{
							tempItem = s._dataToItemDict.getValue(tempData);
							s._selectList.push(tempData);
							if(tempItem)
								tempItem.selected = true;
						}
					}
					else if(!ctrlKey)
					{
						tempData = s._selectList[end];
						s._selectList[end] = s._selectList[ind];
						s._selectList[ind]= tempData;
						--end;
					}
				}
			}
			if(!ctrlKey && end > -1)
			{
				tempVec = s._selectList.splice(0,end + 1);
				len = tempVec.length;
				while(--len>-1)
				{
					tempItem = s._dataToItemDict.getValue(tempVec[len]);
					if(tempItem)
					{
						tempItem.selected = false;
					}
				}
			}
			if(s.hasEventListener(GYViewEvent.SELECTED) && s._mouseSelect)
			{
				s.dispatchEvent(new GYViewEvent(GYViewEvent.SELECTED));
				s._mouseSelect = false;
			}
		}
		/**纵向滚动条*/
		public get vScroller():GYScrollBarV
		{var s = this;
			return s._vScroller;
		}
		/**@inheritDoc*/
		public updateGrid():void
		{var s = this;
			var h:number;
			var i:number,j:number;
			var grid:IItemRender;
			for(i=0;i<s._rows;++i)
			{
				for(j=0;j<s._cols;++j)
				{
					grid=s._grids[i*s._cols + j];
					grid.width = s._boxW;
					grid.height = s._boxH;
				}
			}
			h = s._boxH + s._paddingB;
			s._max=s._dataProvider == null?s.baseHeight:Math.max(Math.ceil(s._dataProvider.length/s._cols) * h - s._paddingB,s.baseHeight);
			s._vScroller.maximum = s._max-s.baseHeight + s._scrollPadTop + s._scrollPadBottom;
			s._vScroller.barPercent = s.baseHeight/s._max;
			if(s._vScroller.value > s._vScroller.maximum)
				s._vScroller.value = s._vScroller.maximum;
			s.scrollChange();
			if(s.hasEventListener(GYViewEvent.GRID_UPDATE))
				s.dispatchEvent(new GYViewEvent(GYViewEvent.GRID_UPDATE));
		}
		/**@inheritDoc*/
		public get dataProvider():Array<any>
		{var s = this;
			return s._dataProvider;
		}
		public set dataProvider(val:Array<any>)
		{var s = this;
			if(!s._keepSelected)
			{
				s._selectedData = null;
				s._selectIndex = -1;
				if(s._canSelectNum > 1)
					s._selectList.length = 0;
			}
			var h:number=s._boxH + s._paddingB;
			s._dataProvider=(val?val:[]);
			if(!s._virtual_layout)
			{
				s.rows = s._dataProvider.length;
				if(!s._boxNumUpdate)
					s.boxNumChange(true);
			}
			if(s._boxNumUpdate)
				s._boxNumUpdateReset = true;
			s._max=Math.max((s._cols == 0?0:Math.ceil(s._dataProvider.length/s._cols) * h - s._paddingB),s.baseHeight);
			s._vScroller.maximum = s._max-s.baseHeight + s._scrollPadTop + s._scrollPadBottom;
			s._vScroller.barPercent = s.baseHeight/s._max;
			if(s._vScroller.position > s._vScroller.maximum)
				s._vScroller.position = s._vScroller.maximum;
			s.scrollerPolicy = s._scrollerPolicy;
			s.scrollChange(null,true);
		}
		private scrollChange(e:GYScrollerEvent=null, update:boolean = false, updatePos:boolean = true)
		{var s = this;
			if(s._dataProvider==null)
				return;
			if(s._boxNumUpdate)
				return;
			var val:number;
			var w:number;
			var h:number;
			var line:number;
			var offset:number;
			var i:number,j:number;
			var grid:IItemRender;
			var nowLine:number;
			val = s._vScroller.position;
			if(!s._virtual_layout)
			{
				s.clipY = val;
				return;
			}
			w=s._boxW + s._paddingR;
			h=s._boxH + s._paddingB;
			offset=val % h;
			nowLine=(val / h >> 0);			
			line = 0;
			if(!update)
			{
				line=s._lastLine-nowLine;
				if(line < 0)
				{
					if(-line<s._rows)
					{
						for(i=0;i<-line;++i)
						{
							for(j=0;j<s._cols;++j)
							{
								grid=s._grids.shift();
								s._grids.push(grid);
							}
						}
					}
				}
				else if(line > 0)
				{
					if(line<s._rows)
					{
						for(i=0;i<line;++i)
						{
							for(j=0;j<s._cols;++j)
							{
								grid=s._grids.pop();
								s._grids.unshift(grid);
							}
						}
					}
				}
			}
			var tempLine:number= s._rows + line - 1;
			var isSet:boolean;
			var ind:number;
			for(i=0;i<s._rows;++i)
			{
				isSet = (line > 0 && i < line || line < 0 && i > tempLine || update);
				for(j=0;j<s._cols;++j)
				{
					grid = s._grids[i*s._cols + j];
					ind = (nowLine+i)*s._cols+j;
					grid.itemIndex = ind;
					var obj:any=s._dataProvider[ind];
					if(isSet)					
						s.setGrid(grid,obj);											
					if(updatePos)						
					{
						grid.x = w * j;
						grid.y = h * i - offset;
					}					
				}
			}
			s._lastLine = nowLine;
		}
		public set rows(val:number)
		{let s = this;
			if(val < 0)return;
			if(val == s._rows)return;			
			s._rows = s._virtual_layout?val:Math.ceil((s._dataProvider && s._cols > 0)?s._dataProvider.length / s._cols:0);
			s.invalidBoxNum();
		}
		public get rows():number
		{
			return this._rows;
		}
		public set cols(val:number)
		{let s = this;
			if(val < 0)return;
			if(val == s._cols)return;
			s._cols = val;
			s.invalidBoxNum();
		}
		public get cols():number
		{
			return this._cols;
		}
		protected boxNumChange(update:boolean=false):void
		{
			var i:number,j:number;
			var grid:IItemRender;
			var ind:number;
			var isNew:Boolean;
			var w:number;
			var h:number;
			var len:number;
			var offset:number;
			let s =this;
			w = s._boxW + s._paddingR;
			h = s._boxH + s._paddingB;			
			offset = s._virtual_layout?s._vScroller.position % h:0;
			len = s._grids.length;
			for(i=0;i<s._rows;++i)
			{
				for(j=0;j<s._cols;++j)
				{
					ind = i * s._cols + j;
					isNew = s._grids[ind] == null;
					if(isNew)
					{
						s._grids[ind] = grid = s.getGrid();
					}
					else
						grid = s._grids[ind];
					if(s._dataProvider && (isNew || update))
					{
						grid.itemIndex = ind;
						s.setGrid(grid,s._dataProvider[s._lastLine*s._cols + ind]);
						grid.selected = s._selectedData!=null && grid.getData() == s._selectedData;
					}
					grid.x = w * j;
					grid.y = h * i - offset;
					s.addElementAt(grid,0);
				}
			}
			i = s._cols * s._rows;
			for(;i<len;++i)
			{
				grid = s._grids[i];
				if(grid.parent)
					(<any>grid.parent).removeElement(grid);
			}
			s._grids.length = s._cols * s._rows;
		}
		/**刷新列表可见的所有项*/		
		public updateItems():void
		{var s = this;
			s.scrollChange(null,true, false);
		}
		public set height(val:number)
		{var s = this;
			if(s.$height == val)
				return;
			s._innerHeight = s._vScroller.height = s.group_height = val;
			var h:number = s.baseHeight;
			s._max=s._dataProvider == null?h:Math.max(Math.ceil(s._dataProvider.length/s._cols) * (s._boxH + s._paddingB) - s._paddingB,h);
			s._vScroller.maximum = s._max - h + s._scrollPadTop + s._scrollPadBottom;
			s._vScroller.barPercent = h/s._max;
			s.scrollerPolicy = s._scrollerPolicy;
			s.rows = (s._boxH + s._paddingB) > 0?Math.ceil(s._innerHeight / (s._boxH + s._paddingB)) + 1:1;
		}
		public get height():number
		{var s = this;
			return egret.superGetter(GYGridV, this, "height");
		}		
		public set width(val:number)
		{var s = this;			
			if(s.$width == val)
				return;
			s._innerWidth = val;
			s.group_width = val + (s._vScroller.parent?s._vScroller.width:0);
			s.cols = (s._boxW + s._paddingR > 0)?(s._innerWidth / (s._boxW + s._paddingR)>>0):0;
		}
		public get width():number
		{var s = this;			
			return egret.superGetter(GYGridV, this, "width");
		}
		protected wheelRoll(e)
		{var s = this;
			if(!s._wheelScroll)return;
			if(s._isDragging && s.dragForbiddenWheel)return;
			var val:number;
			val = s._wheelStep == 0?s._boxH:s._wheelStep;	
			if(e.deltaY > 0)
				s._vScroller.position += val;
			else
				s._vScroller.position -= val;
		}
		/**滚动条 0自动 1显示 2不显示*/
		public set scrollerPolicy(val:number)
		{var s = this;
			s._scrollerPolicy=val;
			var show:boolean;
			if(s._scrollerPolicy == 0)
			{
				if(s._vScroller.barPercent < 1)
					show = true;
				else
					show = false;
			}
			else if(s._scrollerPolicy == 1)
				show = true;
			else
				show = false;
			if(show)
			{
				if(s._vScroller.parent == null)
				{
					s.baseAdd(s._vScroller);					
					s.group_width = s._innerWidth + s._vScroller.width;
				}
			}
			else
			{
				if(s._vScroller.parent)
				{
					s.baseRemove(s._vScroller);
					s.group_width = s._innerWidth;
				}
			}
		}
		protected downGroup(e:egret.TouchEvent)
		{var s = this;
			if(s.mouseX >= s._vScroller.x && s.mouseX <= s._vScroller.x + s._vScroller.width)
				return;
			s._touchId = e.touchPointID;
			if(GYSprite.pushGlobalDrag(this))
				s.groupDrag();
			else
				s.addEventListener(GYEvent.GLOABL_DRAG, s.globalDragCall,s);
		}
		protected dragLoop(t:number):void
		{var s = this;
			var mY:number;
			let nt:number;
			let frameParam:number;
			let yFlag:boolean;
			let temp:number;
			nt = Date.now();
			frameParam = 1000/egret.ticker.$frameRate|0;			
			yFlag = s._moveYTime < 100;			
			s._moveYTime = yFlag?s._moveYTime + Math.min(frameParam,nt - s._lastYDragTime):Math.min(frameParam,nt - s._lastYDragTime);
			mY = s.mouseY - s._clipRect.y;
			s._lastYDragTime = s._lastXDragTime = nt;
			temp = s.tempY - mY;
			if(s._dragLock || Math.abs(temp) > s.dragValue)
			{
				s._isDragging = true;
				s.dragLock = true;
				s.easeSpeedY = yFlag?s.easeSpeedY + temp:temp;
				s._vScroller.position += temp;
				s.tempY = mY;
				if(s._vScroller.position == 0 && s.easeSpeedY < 0 || s._vScroller.position == s._vScroller.maximum && s.easeSpeedY > 0)
				{
					if(GYSprite.shiftGlobalDrag(1))
						s.clearGlobalDrag();
				}
			}
			else if(GYLite.GYSprite.hasGlobalHDrag())
			{
				let dragMoveX:boolean;
				var mX:number = s.mouseX - s._clipRect.x;
				dragMoveX = Math.abs(s.tempX - mX) > s.dragValue;
				s.tempX = mX;
                if(dragMoveX)
					++GYLite.GYSprite.globalHDrag;
                if(GYLite.GYSprite.globalHDrag > GYLite.GYSprite.globalHDragCount)
                {
                    if (GYLite.GYSprite.shiftGlobalDrag(1))
                        s.clearGlobalDrag();
                }
			}
		}
		protected groupDrag():void
		{var s = this;
			if(s._vScroller.tween)
				s.dragLock = true;
			s._vScroller.stopScroll();
			// CommonUtil.addStageLoop(s.dragLoop,s);
			GYSprite.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			s._lastYDragTime = s._lastXDragTime = Date.now();
			s.tempY = s.mouseY - s._clipRect.y;
			s._moveYTime = s.easeSpeedY = 0;
			s._scrollToPos = NaN;
			GYSprite.addStageDown(s,s.upGroup, s);
			s.addEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);
		}		
		protected groupDragStop():void
		{var s = this;
			if(s.tempY != s.tempY)return;
			s._isDragging = false;
			s.removeEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);
			// CommonUtil.delStageLoop(s.dragLoop,s);
			let dis:number,minDis:number;
			let temp:number,tarPos:number,addDis:number;
			let frameParam:number;
			frameParam = 1000/egret.ticker.$frameRate;
			GYSprite.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			let nt:number = Date.now();			
			let dt:number = s._moveYTime;
			let spd:number;
			if(dt > 0 && nt - s._lastYDragTime < s._easeTriggerTime && (s.easeSpeedY > s.easeValue || s.easeSpeedY < -s.easeValue))
			{
				spd = s.easeSpeedY / dt * frameParam * s.speedParam;
				dis = (s._vScroller.limitMax == s._vScroller.limitMax && s._vScroller.limitMax < s._vScroller.maximum)?s._vScroller.limitMax:s._vScroller.maximum;
				minDis = (s._vScroller.limitMin == s._vScroller.limitMin && s._vScroller.limitMin > 0)?s._vScroller.limitMin:0;
				addDis = Math.abs(spd) * spd * s._easeSpeedValue;
				temp = s._vScroller.position + addDis;
				if(temp < minDis)
				{
					tarPos = minDis;
					addDis = tarPos - s._vScroller.position;
				}						
				else if(temp > dis)
				{
					tarPos = dis;
					addDis = tarPos - s._vScroller.position;
				}
				else
				{
					tarPos = temp;
					// addMaxDis = addDis;	
				}				
				s._vScroller.scrollToPosition(tarPos, (temp < minDis || temp > dis)?s._easeTime:Math.abs(addDis / spd * frameParam * 2));
			}
			else if(s._scrollPosLimit == s._scrollPosLimit)
			{
				s.scrollEnd();
			}
			s.tempY = NaN;
			s.dragLock = false;
		}

		public scrollToNextItem():number
		{let s =this;			
			let pos:number;
			let pad:number;
			let nextPos:number;
			if(!s._overlying)
			{				
				if(s._vScroller.tween)return;
			}
			nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s._vScroller.position;
            if(nextPos > s._vScroller.maximum)return;
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._boxH + s._paddingB);
			pos = ((nextPos / pad >> 0) + 1) * pad;
			pos = pos > s.vScroller.limitMax?s.vScroller.limitMax:(pos > s.vScroller.maximum?s.vScroller.maximum:pos);
			s.vScroller.scrollToPosition(pos);
			s._scrollToPos = pos;
			return pos;
		}		
		public scrollToPreItem():number
		{let s =this;
			let pos:number;
			let pad:number;
			let nextPos:number;
			if(!s._overlying)
			{
				if(s._vScroller.tween)return;
			}
			nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s._vScroller.position;
			if(nextPos < 0)return;			
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._boxH + s._paddingB);
			if(nextPos % pad == 0)
				pos = ((nextPos / pad >> 0) - 1) * pad;
			else	
				pos = ((nextPos / pad >> 0) * pad);
			pos = pos < s.vScroller.limitMin?s.vScroller.limitMin:(pos < 0?0:pos);
			s.vScroller.scrollToPosition(pos, s.scrollNextTime == s.scrollNextTime?s.scrollNextTime:pad);
			s._scrollToPos = pos;
			return pos;
		}
		protected scrollEnd(e:GYScrollerEvent=null):void
		{let s =this;
			if(s._scrollPosLimit != s._scrollPosLimit)return;
			if(s._scrollToPos != s._scrollToPos || s._scrollToPos == s._scrollToPos && Math.abs(s._scrollToPos - s._vScroller.position) > 1)
			{
				s._scrollToPos = NaN;
				if(s.easeSpeedY > 0)
					s.scrollToNextItem();
				else if(s.easeSpeedY < 0)
					s.scrollToPreItem();
				else
				{
					let offset:number;
					offset = s.vScroller.position % s.scrollPosLimit;
					if(offset > 0)
					{
						if(offset > s.scrollPosLimit / 2)
						{
							s.scrollToNextItem();
						}
						else
						{
							s.scrollToPreItem();
						}
					}				
				}
				s.easeSpeedY = 0;
			}
			else
				s._scrollToPos = NaN;
		}
	}
}